package com.whjk.core.security.component;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.whjk.core.common.api.Result;
import com.whjk.core.security.config.IgnoreUrlsConfig;
import com.whjk.core.security.entity.SecurityUserEntity;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@Slf4j
@Component
public class JWTAuthenticationFilter extends OncePerRequestFilter {
    @Autowired
    IgnoreUrlsConfig ignoreUrlsConfig;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        String requestURI = request.getRequestURI();

        if (ignoreUrlsConfig.getUrls().contains(requestURI)) {
            chain.doFilter(request, response);
            return;
        }
        String header = request.getHeader("AccessToken");
        boolean notValid = StringUtils.isBlank(header);
        if (notValid) {
            chain.doFilter(request, response);
            return;
        }

        try {
            // UsernamePasswordAuthenticationToken 继承 AbstractAuthenticationToken 实现 Authentication
            //  所以当在页面中输入用户名和密码之后首先会进入到 UsernamePasswordAuthenticationToken验证(Authentication)，
            UsernamePasswordAuthenticationToken authentication = getAuthentication(header, response);
            SecurityContextHolder.getContext().setAuthentication(authentication);
        } catch (Exception e) {
            e.toString();
        }

        chain.doFilter(request, response);
    }

    private UsernamePasswordAuthenticationToken getAuthentication(String header, HttpServletResponse response) {

        //  用户名
        String username = null;
        List<String> rolesList = new ArrayList<>();
        // 权限
        // List<GrantedAuthority> authorities = new ArrayList<>();

        Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
        SecurityUserEntity extendUserBean = null;
        try {
            //  解析token
            Claims claims = JwtUtil.verifyJwt(header);
            //logger.info("claims：" + claims);
            //   获取用户名
            username = claims.get("name").toString();
           // logger.info("name：" + username);
            Object o = claims.get("roles");
            if (o != null) {
                // 获取权限
                String string = claims.get("roles").toString();
                authorities.add(new SimpleGrantedAuthority("ROLE_" + string));
            }
            //   获取用户名
            Object o1 = claims.get("user");
            Gson gson = new Gson();
            extendUserBean = gson.fromJson(gson.toJson(o1), new TypeToken<SecurityUserEntity>() {
            }.getType());
        } catch (ExpiredJwtException e) {
            response.setContentType("application/json;charset=utf-8");
            response.setStatus(HttpServletResponse.SC_OK);
            PrintWriter out = null;
            try {
                out = response.getWriter();
                out.write(new ObjectMapper().writeValueAsString(Result.er(401, "登录已失效，请重新登录")));
            } catch (Exception jsonProcessingException) {
                jsonProcessingException.printStackTrace();
            }
            out.flush();
            out.close();
        } catch (Exception e) {
            response.setContentType("application/json;charset=utf-8");
            response.setStatus(HttpServletResponse.SC_OK);
            PrintWriter out = null;
            try {
                out = response.getWriter();
                out.write(new ObjectMapper().writeValueAsString(Result.er(401, "解析token错误")));
            } catch (Exception jsonProcessingException) {
                jsonProcessingException.printStackTrace();
            }
            out.flush();
            out.close();

        }
        if (StringUtils.isNotBlank(username)) {
            //  踩坑提醒 此处password不能为null
            UserAuthentication userAuthentication = new UserAuthentication(username, "", authorities);
            userAuthentication.setExtendUserBean(extendUserBean);
            //    User principal = new User(username, "", authorities);
            return new UsernamePasswordAuthenticationToken(userAuthentication, null, authorities);
        }
        return null;
    }
}